[QEMU] pci: Unaligned config read/write overflow
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 28 Nov 2006 13:46:10 +0000 (13:46 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Tue, 28 Nov 2006 13:46:10 +0000 (13:46 +0000)
The default config read/write handlers allows a 4-byte read/write at
address 255.  This can clobber the field after the config area.  This
happens to be the PCIBus pointer in the PCIDevice structure.

This patch stops this from reducing the read/write to the (largest
multiple of 2) number of bytes within the config area.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
tools/ioemu/hw/pci.c

index 77737c8615262a872060d33923e7ef2dbd3f3889..cea81f7b7f43c0e1adc18df378dfd80a68caae2d 100644 (file)
@@ -221,16 +221,23 @@ uint32_t pci_default_read_config(PCIDevice *d,
                                  uint32_t address, int len)
 {
     uint32_t val;
+
     switch(len) {
-    case 1:
-        val = d->config[address];
-        break;
-    case 2:
-        val = le16_to_cpu(*(uint16_t *)(d->config + address));
-        break;
     default:
     case 4:
-        val = le32_to_cpu(*(uint32_t *)(d->config + address));
+       if (address <= 0xfc) {
+           val = le32_to_cpu(*(uint32_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 2:
+        if (address <= 0xfe) {
+           val = le16_to_cpu(*(uint16_t *)(d->config + address));
+           break;
+       }
+       /* fall through */
+    case 1:
+        val = d->config[address];
         break;
     }
     return val;
@@ -333,7 +340,8 @@ void pci_default_write_config(PCIDevice *d,
 
             d->config[addr] = val;
         }
-        addr++;
+        if (++addr > 0xff)
+               break;
         val >>= 8;
     }